#include "Player.h"

//ctor
Player::Player(){
}
Player::Player(string playerName){
	name = playerName;
}

//dtor
Player::~Player(){
    myInventory.clear();
}

//inisialisasi
void Player::initialize(){
	//pertama game dimulai dari rumah
	curArea = HOME_CODE;
	//koordinat portal masuk
	curPos.x = DEFAULT_PORTAL_X;
	curPos.y = DEFAULT_PORTAL_Y;
	//arah default
	curDir = DEFAULT_DIRECTION;
	//balance
	balance = DEFAULT_BALANCE;
	//inventory
	myInventory.clear();
	//buat coba sell
	InventoryElem iE;
	iE.amount = 1;
	iE.item = CARROT_FRUIT_CODE;
	myInventory.push_back(iE);
	//timeLeft
	timeLeft = MAX_TIME;
	//day
	day = 1;
}

void Player::initialize(SaveInfo saveInfo){
	//pertama game dimulai dari rumah
	curArea = HOME_CODE;
	//koordinat portal masuk
	curPos.x = saveInfo.PI.curPos.x;
	curPos.y = saveInfo.PI.curPos.y;
	//arah default
	curDir = saveInfo.PI.curDir;
	//balance
	balance = saveInfo.PI.balance;
	//inventory
	myInventory.clear();
	myInventory = saveInfo.PI.myInventory;
	//timeLeft
	timeLeft = saveInfo.PI.timeLeft;
	//day
	day = saveInfo.PI.day;
}
//get & set
//mendapatkan area player
AreaType Player::getCurArea(){
	return curArea;
}

//mendapatkan waktu yang tersisa untuk player
Time Player::getTimeLeft(){
	return timeLeft;
}

//mendapatkan daftar inventory player
Inventory Player::getMyInventory(){
	return myInventory;
}

//mendapatkan nama player
string Player::getName(){
	return name;
}

//mendapatkan saldo player
int Player::getBalance(){
	return balance;
}

//menteleport player ke area lain
void Player::teleport(AreaType area){
	curArea = area;
	//koordinat portal masuk
	curPos.x = DEFAULT_PORTAL_X;
	curPos.y = DEFAULT_PORTAL_Y;
	curDir = DEFAULT_DIRECTION;
}

//farm method

//cangkul terrain di depan bila isPlowable. jika berhasil, return true, gagal, return false
void Player::plow(Farm& farm){

    if (farm.isPlowable(getFrontPos())){
		farm.setPlowed(getFrontPos());

	}

}

//tanam terrain di depannya bila isPlantable dan bibitnya ada di slot tersebut. jika berhasil, return true, gagal, return false
void Player::seed(Farm& farm,int slot){
	if (farm.isPlantable(getFrontPos()) && farm.isPlowed(getFrontPos())){
		farm.setPlanted(getFrontPos(),myInventory[slot-1].item);
		--myInventory[slot-1].amount;
		myInventory = cleanInventory(myInventory);
	}
	else
		throw "Either it's not yet plowed or it's not plantable.";
}

//jika tanaman didepannya dapat dipanen, return true dan tambahkan inventory. jika inventory penuh atau tanaman tidak harvestable, return false
bool Player::harvest(Farm& farm){
	if(farm.isHarvestable(getFrontPos())){
		//cek apakah buah sejenis ada di inventory
		FruitType fruitType = farm.getFruitType(getFrontPos());
		bool isFruitExist=false;
		int i = 0;
		while((i<=3) && !isFruitExist){
			isFruitExist=(fruitType == myInventory[i].item);
			i++;
		}
		//bila ada, tambahkan amountnya
		if (isFruitExist){
			farm.setHarvested(getFrontPos());
			++myInventory[i-1].amount;
			return true;
		}
		else{
			//bila inventory tidak penuh, isikan. bila penuh, return false
			if(myInventory.size()==3)
				return false;
			else{
				farm.setHarvested(getFrontPos());
				InventoryElem inventoryElem;
				inventoryElem.amount = 1;
				inventoryElem.item = fruitType;
				myInventory.push_back(inventoryElem);
				return true;
			}
		}

	}
	else
		return false;
}


//home method
//set timeLeft to MAX_TIME
void Player::sleep(){
	timeLeft = MAX_TIME;
	curArea = HOME_CODE;
	day += 1;
}

//store method
//jual barang di inventory jika itu buah dan jumlahnya cukup dan return true, else, return false
bool Player::sell(int slot,int amount){
	//cek slot tersebut kosong atau tidak
	if((unsigned)slot<=(myInventory.size())){
		//cek apakah jumlah cukup atau tidak
		if(amount<=myInventory[slot-1].amount){
			//tambahkan saldo, kurangi jumlah
			incBalance(amount*getPrice(myInventory[slot-1].item));
			myInventory[slot-1].amount -= amount;
			myInventory = cleanInventory(myInventory);
			return true;
		}
		else{
		    incBalance(amount*getPrice(myInventory[slot-1].item));
		    myInventory[slot-1].amount = 0;
		    myInventory = cleanInventory(myInventory);
		    return true;
		}
	}
	else
		return false;
}

//tambahkan balance sebanyak int
void Player::incBalance(int money){
	balance += money;
}

//if balance is sufficient, return true and increase inventory, else false
bool Player::buy(ItemType item ,int amount){
	int total = amount*getPrice(item);
	//cek apakah uang cukup
	if(balance>=total){
		//cek apakah b sejenis ada di inventory
		bool isItemExist=false;
		int i = 0;
		while(((unsigned) i < myInventory.size()) && !isItemExist){
			isItemExist=(item == myInventory[i].item);
			i++;
		}
		//bila ada, tambahkan amountnya
		if (isItemExist){
			myInventory[i-1].amount += amount;
			decBalance(total);
			return true;
		}
		else{
			//bila inventory tidak penuh, isikan. bila penuh, return false
			if(myInventory.size()==3)
				return false;
			else{
				InventoryElem inventoryElem;
				inventoryElem.amount = amount;
				inventoryElem.item = item;
				myInventory.push_back(inventoryElem);
				decBalance(total);
				return true;
			}
		}
	}
	else
		return false;
}

//mengetahui jenis item dari slot (SEED/FRUIT)
ItemType Player::getItemType(int slot){
	return ((myInventory[slot-1].item<=5) ? FRUIT : SEED);
}

//decrease player's balance
void Player::decBalance(int money){
	balance -= money;
}

//bersihkan inventory dari barang berjumlah kosong
Inventory Player::cleanInventory(Inventory oldInventory){
	Inventory newInventory;
	Inventory::iterator iter;
	for(iter = oldInventory.begin(); iter != oldInventory.end(); iter++ ) {
		if (iter->amount > 0)
			newInventory.push_back(*iter);
	}
	oldInventory.clear();
	return newInventory;
}

//mengembalikan true bila pemain menghadap ke jalan
bool Player::isFaceRoad(){
	int x = getFrontPos().x;
	int y = getFrontPos().y;
	return ((x<0)||(x>FARM_HEIGHT-1)) || ((y<0)||(y>FARM_WIDTH-1));
}

//kurangi waktu pemain
void Player::decTimeLeft(){
	timeLeft-=1;
}

//dapatkan waktu pemain
int Player::getDay(){
    return day;
}

//mengecek bisa dimakan atau tidak
bool Player::isCanEat(int slot){
	ItemType itemMakan = myInventory[slot-1].item;
	if ((itemMakan == FARM_CARROT_SEED)||(itemMakan == FARM_CHILLI_SEED) || (itemMakan == FARM_MELON_SEED) ||(itemMakan == FARM_STRAWBERRY_SEED) || (itemMakan == FARM_TOMATO_SEED)){
		return false;
	}else{
		return true;
	}
}

//memakan item pada suatu slot
bool Player::eating(int slot){
	if (myInventory.size()< (unsigned) slot)
        return false;
    ItemType itemMakan = myInventory[slot-1].item;
	if (isCanEat(slot)) {
		if (itemMakan == CARROT_FRUIT_CODE){
			timeLeft += 3;
			if (timeLeft>MAX_TIME){
				timeLeft=MAX_TIME;
			}
		} else if (itemMakan == TOMATO_FRUIT_CODE){
			timeLeft += 10;
			if (timeLeft>MAX_TIME){
				timeLeft=MAX_TIME;
			}
		} else if (itemMakan == STRAWBERRY_FRUIT_CODE){
			timeLeft += 20;
			if (timeLeft>MAX_TIME){
				timeLeft=MAX_TIME;
			}
		} else if (itemMakan == MELON_FRUIT_CODE){
			timeLeft = MAX_TIME;
		} else {
			sleep();
		}
		myInventory[slot-1].amount -= 1;
		return true;
	}
	else
        return false;
}

void Player::getSaveInfo(SaveInfo& saveInfo){
    saveInfo.PI.balance = balance;
    saveInfo.PI.curArea = curArea;
    saveInfo.PI.curDir = curDir;
    saveInfo.PI.curPos = curPos;
    saveInfo.PI.day = day;
    saveInfo.PI.myInventory = myInventory;
    saveInfo.PI.name = name;
    saveInfo.PI.timeLeft = timeLeft;
}
